#ifndef QUEUE_H
#define QUEUE_H

#include <stdint.h>

#include "portmacro.h"
#include "list.h"

#define queueSEND_TO_BACK                     ( ( BaseType_t ) 0 )
#define queueSEND_TO_FRONT                    ( ( BaseType_t ) 1 )
#define queueOVERWRITE                        ( ( BaseType_t ) 2 )

/* Intended for internal use only, and the queues created can only be of the following enumerated types. */
typedef enum 
{
	QUEUE_TYPE_BASE = 0x00,
}QueueType_t;       

/* The head and tail pointers of the queue. */
typedef struct QueuePointers
{
	/*
	 * Definition : The pcTail pointer points to the end of the queue storage area, which is the position after the last element in the queue. 
	 *              In practice, an additional byte of space is typically allocated as a marker to facilitate handling boundary conditions in a circular queue.
 	 * Purpose    : used to identify the boundaries of the queue storage area. In cases where the queue is full or empty, 
	 *               pcTail helps distinguish between these two states and ensures that queue operations do not result in out-of-bounds accesses.
	 */
	int8_t * pcTail;     

	/*
	 * Definition : The pcReadFrom pointer points to the position of the last element that was read (dequeued) from the queue.
	 * Purpose    : In dequeuing operations, pcReadFrom is used to determine from which position to retrieve elements. After dequeuing, 
	 *              pcReadFrom is updated to point to the next element position to be read. This allows the queue to manage data in a FIFO (First-In-First-Out) manner.
	 */
	int8_t * pcReadFrom;   
}QueuePointers_t;

typedef struct
{
	/*
	 * In queue initialization, pcHead is set to point to the first address of the queue storage area.
	 * It is static and does not change with the enqueuing and dequeuing of elements.
	 */
	int8_t * pcHead;
	
	/*
	 * Whenever a new element is added to the queue, it is placed at the position pointed to by pcWriteTo. 
	 * After the enqueue operation is completed, pcWriteTo is updated to point to the next available storage position.
	 */
	int8_t * pcWriteTo;
	
	QueuePointers_t pointers;
	
	List_t xTaskWaitingToSend;                   /*< List of tasks that are blocked waiting to post onto this queue.  Stored in priority order. */
	List_t xTaskWaitingToReceive;                /*< List of tasks that are blocked waiting to read from this queue.  Stored in priority order. */
	
	volatile UBaseType_t uxMessagesWaiting;      /*< The number of items currently in the queue. */
	
	UBaseType_t uxLength;                        /*< The number of itmes it will hold. */
	UBaseType_t uxItemSize;                      /*< The size of each item that the queue will hold. */
	
	volatile int8_t cRxLock;                     /*< Read  Lock */
	volatile int8_t cTxLock;                     /*< Write Lock */
}Queue_t;

typedef Queue_t * QueueHandle_t;


#define xQueueSend(xQueue, pvItemToQueue, xTicksToWait) \
			xQueueGenericSend( ( xQueue ), ( pvItemToQueue ), ( xTicksToWait ), queueSEND_TO_BACK)

#if ( configSUPPORT_STATIC_ALLOCATION == 1 )
	#define xQueueCreateStatic( uxQueueLength, uxItemSize, pucQueueStorate, pxQueueBuffer ) \
          xQueueGenericCreateStatic( ( uxQueueLength ), ( uxItemSize ), ( pucQueueStorage ), ( pxQueueBuffer ) ( queueQUEUE_TYPE_BASE ) )
#endif /* configSUPPORT_STATIC_ALLOCATION */

#endif /* QUEUE_H */
